"""
Copyright 2009, Thomas Dejanovic, Jay Shurtz.
 
This is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of
the License, or (at your option) any later version.

This software is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this software; if not, write to the Free
Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA, or see the FSF site: http://www.fsf.org.

This module holds the base class for all hatch design visitor objects.  
Import this module as "from hatch_visitor import * ".
"""

id = "$Id: hatch_visitor.py 667 2010-07-01 00:12:17Z jayshurtz $"
# $URL: http://hatch.googlecode.com/svn/tags/taggle_release_2.2/hatch/hatch_visitors/hatch_visitor.py $
# $Author: jayshurtz $
version = " ".join(id.split()[1:3])


import to_hatch_structure
from hatch_log import *
from hatch_iterators import *


class HatchVisitor(object):
    """ Base class for all hatch design visitor objects.
    """
    def __init__(self, temporaryProperties=[]):
        """ 'temporaryProperties' is a list of temporary properties that should 
                be deleted after visiting.
        """
        self.temporaryProperties = temporaryProperties

    def visit(self, hatchNode):
        """ Visit a hatch design, recursing downwards from the top-most parent node.
            Different visitor objects can do any number of different things, such as
            checking node properties, setting node addresses, etc.
            'hatchNode' should be the top node in a hatch design.
        """
        logger.info(self.__class__.__name__ + " visiting " + hatchNodeClassAndName(hatchNode))
        #if hatchNode.parent is not None:    # check for top node.
        #    raise AssertionError, hatchNodeErrorString(hatchNode, self.__class__.__name__ + " class can only visit the top hatch node in a design.")
        self.visit_function(hatchNode)
        self.deleteTemporaryProperties(hatchNode)

    def visit_function(self, hatchNode):
        """ Override this function with a function that does the actual work 
            involved in visiting a hatch design tree from the top down.
            'hatchNode' should be the top node in a hatch design.
        """
        raise NotImplementedError, self.__class__.__name__ + " does not define a '" + self.visit_function.func_name + "' method."   # Force override.

    def deleteTemporaryProperties(self, hatchNode):
        """ Delete any temporary hatch node properties created during visit.
            'hatchNode' should be the top node in a hatch design.
            'tempProps' should be the list of temporary properties, defaults 
                to 'self.temporaryProperties'.
        """
        for prop in self.temporaryProperties:
            for node in HatchNodeIteratorDepthFirst(hatchNode):
                try:
                    del node.properties[prop]
                except KeyError, e:
                    pass    # Property does not exist, skip it.


# Main for test
if __name__ == "__main__":

    consoleHandler.setLevel(logging.DEBUG)

    ie = HatchVisitor(['delete_me'])

    from hatch_nodes.hatch_node_physical import HatchNodePhysical
    h0 = HatchNodePhysical('h0', delete_me='delete me!!')
    h1 = HatchNodePhysical('h1')
    h0h1 = HatchNodePhysical('h0h1', h0, h1)

    try:
        ie.visit(h0h1)
    except Exception, e:
        print 'Exception caught: ' + str(e)
    print h0h1.info(recurse=True) # Print properties.

    ie.deleteTemporaryProperties(h0h1)
    print h0h1.info(recurse=True) # Print properties.


